COMMENT \ VID.SLO This is the microcode for vector display i/o. There are two basic macro instructions: VIDIN AC,E: 770000,,0 input from VID with i/o sub sel = ac to contents of effective address. VIDOUT AC,E: 771000,,0 output from contents of effective address to VID with i/o sub sel = ac These get dispatched to by 700 series iots (although the format is more like a non-iot instruction.) ;OPDEF's for FooVision: OPDEF VIDIN [770000,,0] ;In to CPU from FooVision (AC=MAPF) OPDEF VIDOUT [771000,,0] ;Out from CPU to FooVision (AC=MAPF) OPDEF VLDDAT [VIDOUT 1,] ;36 bit format or B,G,R 8 bits each OPDEF VSYDAT [VIDIN 1,] ;Synthesize DATA (also to (E)) OPDEF VLDADR [VIDOUT 2,] ;16 bits right justified OPDEF VSYADR [VIDIN 2,] ;Synthesize ADR (also to (E)) OPDEF VLDBAK [VIDOUT 3,] ;IOB 4-11 (of 36 bit word, 0=MSB) OPDEF VOEVID [VIDIN 4,] ;36 bit format palette(3),(11*PIXEL(3)) OPDEF VOECOL [VIDIN 5,] ;B,G,R 8 bits each right justified OPDEF VWECOL [VIDIN 6,] ;Write enable color map - (E) trashed OPDEF VWEVID [VIDIN 7,] ;Write enable video buffer - (E) trashed OPDEF VLDCOL [VIDOUT 10,] ;36 bit mask XORed with synthesized data OPDEF VLDSIZ [VIDOUT 11,] ;OFFSET,,SIZE (in WDS/FLD (11 PXLS/WD)) OPDEF VLDCTR [VIDOUT 12,] ;B0=video resolution (vs. high res B/W) ;B1=add (don't overwrite) ;B2=carry ;B3=interlace ;B4=NTSC color OPDEF VLDPIX [VIDOUT 13,] ;Inten.(3 bit),line (9 bit),,pixel(10 bit) OPDEF VLDOFF [VIDOUT 14,] ;Y offset,,X offset OPDEF VWEDIV [VIDIN 16,] ;Write enable divide table - (E) trashed OPDEF VWENTS [VIDIN 17,] ;Write enable NTSC table - (E) trashed There are three additional instructions which simulate part of the Stanford-III vector display: OPDEF DPYINI [772000,,0] ;Initialize display OPDEF DPYOUT [773000,,0] ;Interpret Stanford-III display format OPDEF DPYADD [767000,,0] ;Append Stanford-III display format DPYINI POGB ;Take a block of 64 words at E (which contain ;pointers to "shadow" pieces-of-glass, fonts, ;and various other state (used in interrupts)). ;Zero all POG lengths, and blank screen. POGB: POGB+1: ... POGB+15: ;These are pointers to blocks of memory where ;the display list for the previous piece of ;glass is copied. This data is subtracted ;from the image by DPYOUT before adding the ;new display list. POGB+16: ;Window boundaries POGB+17: ... POGB+31: POGB+32: ;Note: These are internal (- at top) coords. POGB+33: ... POGB+47: POGB+48: ;Pointers to fonts (2K each) POGB+49: POGB+50: ... POGB+55: POGB+56: ;State for interrupt recovery POGB+57: POGB+58: POGB+59: ;Non VIC2 only POGB+60:;Non VIC2 only POGB+61: POGB+62: POGB+63: POGB+64: POGB+65: ... POGB+71: DPYOUT POG,E ;Similar to the stanford instruction. Takes (DPYADD) ;a pointer and length for the display list ;for the piece of glass and puts it on the ;screen, deleting (or adding to) the previous ;contents of that piece of glass. E: ,, Below are the two objects (vectors and characters) implemented from the Stanford-III display system: Long Word Vector: !00 10!11 21!22 24!25 27!28!29!30 31!32 35! ! X ! Y ! BRT ! SIZE ! !M ! T ! 0110 ! BRT(color): SIZE: M: T: 0=no change 0=no change 0=relative 0=visible 1=white 1=font 1 1=absolute 1=end point 2=red . 2=invisible 3=yellow . 3=undefined 4=green . (end point) 5=blue . 6=magenta . 7=white(colored) 7=font 7 CHaRacter: !00 06!07 13!14 20!21 27!28 34!35! ! CH1 ! CH2 ! CH3 ! CH4 ! CH5 !1 ! Vector algorithms: X(Y)=X(Y-1)+DXDY INTEN(Y,INT(X(Y)))= 3*(1-FRACT(X)) if A3DYDX GEQ 3 3-A3DYDX*FRACT(X) if A3DYDX < 3 INTEN(Y,INT(X(Y))+1)= 3*FRACT(X) if A3DYDX GEQ 3 3-A3DYDX*(1-FRACT(X)) if A3DYDX < 3 INTEN(Y,INT(X(Y))-K)=INTEN(Y,INT(X(Y))-(K-1))-A3DYDX INTEN(Y,INT(X(Y))+K)=INTEN(Y,INT(X(Y))+(K-1))-A3DYDX where: FRACT(X) =fractional part of X INT(X) =integer part of X X(Y) =X(growing left to right) position as a function of Y(growing top to bottom) INTEN(Y,X) =intensity as a function of position DXDY =slope of X vs. Y A3DYDX =three times the absolute value of the slope of Y vs. X The compromise color/grey level coding is as follows: per word: 0 1 2 3 4 5 6 7 per pixel: 0 sync black black black black black black black 1 sync W 1 W 1 W 1 W 1 W 1 W 1 W 1 2 sync W 2 W 2 W 2 W 2 W 2 W 2 W 2 3 sync W 3 W 3 W 3 W 3 W 3 W 3 W 3 4 sync W 4 R 3 Y 3 G 3 B 3 M 3 W 4 5 sync W 5 R 3 Y 3 G 3 B 3 M 3 W 5 6 sync W 6 R 3 Y 3 G 3 B 3 M 3 W 6 7 sync W 7 R 3 Y 3 G 3 B 3 M 3 W 7 B/W objects are clipped to intensity level 3. Colored objects are always either intensity 0 (blank) or intensity 4. This will make the overlapping of a colored object over one B/W object always come out colored and of the correct intensity. Note that two overlapping colored objects will cancel. Also note that a colored object overlapping two B/W objects which already overlap will not come out correctly colored. Finally, it is still only possible to have one color per word, i.e. two differently colored objects in the same word will overwrite eachother. This code will take interrupts correctly, but not map faults, since it is in general impossible to save all ones state so that one can restart. Specifically, there is no provision currently for saving the micro PC from which you faulted. To get around this failing, it is necessary to "touch" (i.e., reference) each page that the display list might require. This has an unplesant interaction with the scheduler in Tenex, which will frequently not allow the page touching loop to terminate (it has to get all the pages mapped before it can let the code run). To get around this, the code turns off the real time clock before touching and turns it back on after touching so that the code can interrupt as usual. This prevents scheduling due to interrupts from the real time clock during page validation cycles (map operations where the physical memory is actually there, but the map is invalid, usually due to map CONOs.) \ ;Note that VIDTAB (the dispatch table) must appear before VIDIN ;and VIDOUT due to forward referencing problems. %VIDFOO = 0 VIDTAB: ;dispatch table used by both VIDIN and VIDOUT. .REPEAT 16. [ MAPF[%VIDFOO] D[IOD] DEST[HOLD] JUMP[VIDCOM] C800$ %VIDFOO = %VIDFOO + 1 ] ;i/o sub sel = ac. input data and hold for memory write. VIDIN: D[CONST (VIDTAB / 100)] ROT[6] DEST[Q] NORM$ ;form high order 6 bits of table dispatch. D[CONST (VIDTAB \ 100)] ALU[DORQ] DEST[Q] NORM$ ;or in low order 6 bits of table dispatch. D[IR] ROT[13.] MASK[4] ALU[D+Q] SDISP START-IN C600$ ;add ac field and dispatch. start input. VIDOUT: D[MEM] DEST[IOD] NORM$ ;put contents effective address into iod output register. D[CONST (VIDTAB / 100)] ROT[6] DEST[Q] NORM$ ;form high order 6 bits of table dispatch. D[CONST (VIDTAB \ 100)] ALU[DORQ] DEST[Q] NORM$ ;or in low order 6 bits of table dispatch. D[IR] ROT[13.] MASK[4] ALU[D+Q] SDISP START-OUT C600$ ;add ac field and dispatch. start output. VIDCOM: ;common completion. D[IR] ROT[8] COND[OBUS<0] JUMP[MAIN] C600$ ;if VIDOUT, done. jump main. STRT-WRT MEMST$ ;if VIDIN, write as in movem. ;Main A-MEM: INTEN,,FRACT = 1 ;For storage of vector display word POG,,POGB = 7 ;Left by DPYINI .REPEAT XUCODE [ .USE[HIGHMEM] ;If 8K u-mem present, put video code there. ] ;This macro saves the address given as its argument so that returns ;from interrupts can resume operation there. Jumps to VIDINT, which ;saves AMEM, then goes to MAIN. ;WARNING! WARNING !WARNING ;THIS PIECE-OF-SHIT ASSEMBLER WON'T ACCEPT COMPOUND MACRO ARGUMENTS. ;I.E., YOU MUST EVALUATE ARGUMENTS BEFORE INVOKING A MACRO. ;ALSO, IF YOU CHANGE THE LENGTH OF THIS MACRO, REMEMBER TO ALTER THE ;JUMP[. + 9]'S IN VIDRGT AND VIDLFT. .DEFINE VIDSAV[%ADR] [ D[CONST (%ADR / 10000)] ROT[12.] DEST[Q] NORM $ ;Q=high bit (SDISP loads all 16 bits) D[CONST (77 & (%ADR / 100))] ROT[6] ALU[QORD] DEST[Q] NORM $ ;Q=next 6 ADR bits D[CONST (%ADR \ 100)] ALU[QORD] DEST[HOLD] NORM $ ;Q=SAVE ADR D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 58.] ALU[Q+D] DEST[MA] STRT-WRT JUMP[VIDINT] NORM $ ;MA=POGB+58 write SAVE ADR ] ;DPYINI ;Save the POG block pointer for use by DPYOUT. VIDDPI: D[CONST 4] DEST[DEV-ADR] NORM $ ;DEV-ADR=INTERRUPT D[CONST 0] DEST[IOD] START-OUT NORM $ ;TURN OFF INTERRUPTS (SO WE DON'T GO TO THE SCHEDULER) MAPF[6] C800 $ ;BIT 35 = ON/OFF D[CONST 36] DEST[DEV-ADR] NORM $ ;DEV-ADR=36 D[IR] MASK[18.] DEST[POG,,POGB] DEST-A-MEM NORM $ ;POG,,POGB=0,,E ;Zero all lengths. D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB. ALU[0] DEST[HOLD] NORM $ ;HOLD=0 D[CONST 56.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+56. write (0) MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] D[CONST 15.] LLOAD NORM $ ;Touch Loop 16 times VIDIN1: ALU[Q] DEST[MA] NORM $ ;MA=Q read MAPF[NORM-WRT] ALU[Q+1] DEST[Q FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;Q=Q+1 touch D[MEM] ROT[3] MASK[21.] DEST[AR] NORM $ ;AR=BACKGROUND,LENGTH,,BEGINING LSH 3 MASK 21 (LENGTH=0) D[AR] ROT[36. - 3] DEST[MEMSTO] NORM $ ;HOLD=BACKGROUND,0,,BEGINING write ;Initialize the remaining length counter for this piece of glass. D[MEM] MASK[18.] ALU[D-1] DEST[AR] NORM $ ;AR=BEGINING POG-1 D[AR] ALU[D-1] DEST[MA] NORM $ ;MA=BEGINING -2 read max length MAPF[NORM-RD] NORM $ ;WAIT D[MEM] DEST[HOLD] NORM $ ;HOLD=MAX LENGTH Sigh. HOLD and MEM really are different D[AR] DEST[MA] STRT-WRT NORM $ ;MA=BEGINING-1 write remaining length MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] LOOP[VIDIN1] CYLEN[FIXM] $ ;touch and loop ;Turn interrupts back on. D[CONST 4] DEST[DEV-ADR] NORM $ ;DEV-ADR=INTERRUPT D[CONST 1] DEST[IOD] START-OUT NORM $ ;TURN ON INTERRUPTS MAPF[6] C800 $ ;BIT 35 = ON/OFF D[CONST 36] DEST[DEV-ADR] NORM $ ;DEV-ADR=36 ;Clear screen. D[CONST 44] ROT[30.] DEST[IOD] START-OUT COND[HALF] JUMP[VIDNTR] NORM $ ;IOD=440000,,000000 Check HALF VIDHER: MAPF[12] D[CONST 7] ROT[6] DEST[Q] C800 $ ;VLDCTR (overwrite) Q=7*64 (past vert. sync) D[CONST 30.] ROT[3] DEST[AR] NORM $ ;AR=240. (major loops) VIDIN2: D[CONST 57.] LLOAD NORM $ ;Loop 58. times D[CONST 6] ALU[Q+D] DEST[Q] NORM $ ;Q=Q+6 (past horiz. sync) VIDIN3: ALU[Q] DEST[IOD] START-OUT C800 $ ;IOD=Q MAPF[2] C800 $ ;VLDADR D[CONST 7] ROT[33.] DEST[IOD] START-OUT C800 $ ;IOD=700000,,000000 MAPF[1] START-IN C800 $ ;VLDDAT (blank) MAPF[7] C800 $ ;VWEVID C800 $ ;WAIT D[CONST 1] ROT[14.] ALU[Q+D] DEST[IOD] START-OUT C800 $ ;IOD=Q+1 FIELD MAPF[2] C800 $ ;VLDADR D[CONST 7] ROT[33.] DEST[IOD] START-OUT C800 $ ;IOD=700000,,000000 MAPF[1] START-IN C800 $ ;VLDDAT (blank) MAPF[7] ALU[Q+1] DEST[Q] COND[INTRPT] JUMP[VIDNTI] C800 $ ;VWEVID Q=Q+1 If interrupt, save state VIDIN4: LOOP[VIDIN3] C800 $ ;loop D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[VIDIN2] C600 $ ;AR=AR-1 if 0, done. ;Done. ALU[0] DEST[DEV-ADR] SPEC[CLR-HALF] JUMP[GOMAIN] NORM $ ;Reset device address, clear HALF ;Interrupt init VIDNTI: ALU[Q] DEST[HOLD] NORM $ ;HOLD=Q D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 1] ROT[6] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+64. write old Q MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;TOUCH D[AR] DEST[HOLD] NORM $ ;HOLD=AR D[CONST 1] ROT[6] ALU[D+Q+1] DEST[MA] STRT-WRT NORM $ ;MA=POGB+65. write old AR MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;TOUCH D[CONST 1] ROT[35. - 4] DEST[Q] NORM $ ;Q=BIT 4 ON D[PC] ALU[D-1] DEST[PC] NORM $ ;PC=PC-1 D[PC] ALU[DORQ] DEST[CRYOV] NORM $ ;Set HALF flag ALU[0] DEST[DEV-ADR] JUMP[GOMAIN] NORM $ ;Reset dev and disp to intrpt ;Return from init interupt. VIDNTR: MAPF[12] D[10 + POG,,POGB] MASK[18.] DEST[Q] C800 $ ;VLDCTR Q=POGB D[CONST 1] ROT[6] ALU[D+Q+1] DEST[MA] NORM $ ;MA=POGB+65. read old AR MAPF[NORM-RD] D[CONST 30.] ROT[3] DEST[Q FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;TOUCH Q=240. D[MEM] MASK[18.] ALU[Q-D] COND[OBUS<0] JUMP[VIDHER] C600 $ ;Check for half word error (i.e. HALF left from another inst) D[MEM] MASK[18.] DEST[AR] NORM $ ;Restore AR D[10 + POG,,POGB] MASK[18.] DEST[Q] C800 $ ;Q=POGB D[CONST 1] ROT[6] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+64. read old Q MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;TOUCH D[MEM] MASK[6] DEST[Q] COND[-OBUS=0] JUMP[VIDNR1] C550 $ ;Old Q mod 6. D[CONST 1] ROT[6] DEST[Q] NORM $ ;If Q=0, Q=64. VIDNR1: D[CONST 1] ROT[6] ALU[D-Q] LLOAD NORM $ ;Count=remaining till end of line D[MEM] DEST[Q] JUMP[VIDIN4] NORM $ ;Restore Q and resume from interrupt ;DPYOUT (DPYADD) main loop VIDDPA: D[CONST 1] ROT[35. - 4] DEST[Q] NORM $ ;Q=BIT 4 ON D[PC] ALU[DORQ] DEST[CRYOV] NORM $ ;SET HALF FLAG ;FooVision device address (also AMEM block) VIDDPO: D[CONST 4] DEST[DEV-ADR] NORM $ ;DEV-ADR=INTERRUPT D[CONST 0] DEST[IOD] START-OUT NORM $ ;TURN OFF INTERRUPTS (SO WE DON'T GO TO THE SCHEDULER) MAPF[6] C800 $ ;BIT 35 = ON/OFF D[CONST 36] DEST[DEV-ADR] NORM $ ;DEV-ADR=36 ;Save AC=POG in AMEM D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[IR] ROT[13.] MASK[4] DEST[AR] NORM $ ;AR=POG=AC D[AR] ROT[18.] ALU[DORQ] DEST[POG,,POGB] DEST-A-MEM NORM $ ;POG,,POGB=AC,,POGB ;"Touch" the first and last words of the POG block, so we don't ;have to worry about map faulting on them later. D[10 + POG,,POGB] MASK[18.] DEST[Q MA] NORM $ ;Q,MA=POGB MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;TOUCH FIRST WORD D[CONST 11] ROT[3] ALU[D-1] DEST[AR] NORM $ ;AR=71. D[AR] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+71. MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;TOUCH LAST WORD ;Touch E. If left half E (=length of display list)=0, don't bother to ;touch display list. D[IR] MASK[18.] DEST[MA] NORM $ ;MA=E MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;TOUCH D[MEM] MASK[18.] DEST[AR] NORM $ ;AR=BEGINING D[MEM] SPEC[LEFT] COND[OBUS=0] JUMP[VIDTDE] C550 $ ;If LENGTH=0, don't touch (but do continue) ;Touch the display list. Start with the first word, touch every ;512.th word until run off end. Then touch last word. VIDTDL: D[AR] DEST[Q MA] NORM $ ;Q,MA=AR (initially begining of display list) MAPF[NORM-RD] D[CONST 1] ROT[9.] ALU[Q+D] DEST[AR Q FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;AR,Q=AR+1 PAGE touch (post inc) D[IR] MASK[18.] DEST[MA] NORM $ ;MA=E MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;WAIT D[MEM] MASK[18.] ALU[Q-D] DEST[Q] NORM $ ;Q=AR-BEGINING D[MEM] ROT[18.] MASK[18.] ALU[D-Q-1] DEST[Q] COND[-OBUS<0] JUMP[VIDTDL] C600 $ ;Q=LENGTH-(AR-BEGINING)-1 if<0 done D[AR] ALU[Q+D] DEST[MA] NORM $ ;MA=BEGINING+LENGTH-1 MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;TOUCH LAST PAGE ;Touch the POG buffer for this POG. Same as for display list. ;(POGn-2)=POG maximum length ;(POGn-1)=POG words left VIDTDE: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+POG read begining pog buffer MAPF[NORM-RD] NORM $ ;wait D[MEM] MASK[18.] DEST[Q AR] NORM $ ;AR,Q=0,,BEGINING POG BUFFER D[CONST 2] ALU[Q-D] DEST[MA] NORM $ ;MA=POGN-2 read maximum length MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;TOUCH -2nd word D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[AR] NORM $ ;AR=MAXIMUM LENGTH,,BEGINING POG D[AR] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=MAXIMUM LENGTH,,BEGINING POG VIDTNL: D[AR] DEST[Q MA] NORM $ ;Q,MA=AR MAPF[NORM-WRT] D[CONST 1] ROT[9.] ALU[Q+D] DEST[Q FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;AR,Q=AR+1 PAGE touch (post inc) D[CONST 1] ROT[18. + 9.] ALU[Q-D] DEST[AR] NORM $ ;AR=AR+(-1000,,1000) D[AR] SPEC[LEFT] DEST[Q] NORM $ ;Q=REMAINING LENGTH,,0 D[CONST 1] ROT[18.] ALU[Q-D] COND[-OBUS<0] JUMP[VIDTNL] C600 $ ;If LENGTH LEQ 0, done D[10 + INTEN,,FRACT] ROT[18.] MASK[15.] ALU[D-1] DEST[Q] NORM $ ;Q=LENGTH-1 D[10 + INTEN,,FRACT] MASK[18.] ALU[D+Q] DEST[MA] NORM $ ;MA=BEGINING+LENGTH-1 MAPF[NORM-WRT] DEST[FIXMAC-MAPF-WRT] CYLEN[FIXM] $ ;TOUCH LAST WORD ;Touch all 7 fonts. Same as above. VIDTNE: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 48.] ALU[Q+D] DEST[AR] NORM $ ;AR=POGB+48 D[CONST 6] LLOAD NORM $ ;LOOP 7 TIMES VIDTFL: D[AR] ALU[D+1] DEST[MA AR] NORM $ ;MA,AR=AR+1 NORM $ ;WAIT D[MEM] MASK[18.] DEST[MA Q] NORM $ ;MA,Q=FONT 1 MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;TOUCH PAGE .REPEAT 3 [ D[CONST 1] ROT[9.] ALU[Q+D] DEST[MA Q] NORM $ ;MA,Q=Q+1 PAGE MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;TOUCH PAGE ] D[CONST 1] ROT[9.] ALU[D-1] DEST[Q] NORM $ ;Q=1 PAGE - 1 WORD D[MA] ALU[D+Q] DEST[MA] NORM $ ;MA=LAST WORD OF FONT MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] LOOP[VIDTFL] CYLEN[FIXM] $ ;TOUCH PAGE LOOP ;Turn interrupts back on. D[CONST 4] DEST[DEV-ADR] NORM $ ;DEV-ADR=INTERRUPT D[CONST 1] DEST[IOD] START-OUT NORM $ ;TURN ON INTERRUPTS MAPF[6] C800 $ ;BIT 35 = ON/OFF D[CONST 36] DEST[DEV-ADR] NORM $ ;DEV-ADR=36 ;If length rememaining not 0, return from interrupt. D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 56.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+56. read LENGTH REMAINING MAPF[NORM-RD] NORM $ ;WAIT D[MEM] COND[-OBUS=0] JUMP[VIDRET] C550 $ ;If LENGTH REMAINING NEQ 0, return from interrupt ;Check HALF flag to see if DPYADD. COND[-HALF] JUMP[VIDMHL] NORM $ ;If HALF, DPYADD ;Form the display list and POG buffer pointers. D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+POG read LENGTH,,BEGINING MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q] NORM $ ;Q=0,,BEGINING D[MEM] ROT[18.] MASK[15.] ALU[Q+D] DEST[Q] NORM $ ;Q=0,,BEGINING+LENGTH D[IR] DEST[MA] NORM $ ;MA=E read BEGINING MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;WAIT D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[HOLD] NORM $ ;HOLD=DISP BEGINING,,POG BEGINING+LENGTH D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 57.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+57. write DISP BEGINING,,POG BEGINING MAPF[NORM-RD] NORM $ ;WAIT ;Get length of display list and load control register ;with code for addition. Add to length in POG. D[IR] MASK[18.] DEST[MA] NORM $ ;MA=E read LENGTH MAPF[NORM-RD] D[10 + POG,,POGB] MASK[18.] DEST[Q FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;Q=POGB D[MEM] ROT[18.] MASK[15.] DEST[AR HOLD] NORM $ ;AR,HOLD=LENGTH D[CONST 56.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+56. write LENGTH MAPF[NORM-RD] D[CONST 64] ROT[30.] DEST[IOD] START-OUT NORM $ ;IOD=640000,,000000 MAPF[12] D[10 + POG,,POGB] ROT[18.] MASK[18.] ALU[Q+D] DEST[MA] NORM $ ;VLDCTR (add) MA=POGB+POG read BACK,LENGTH,,BEGIN MAPF[NORM-RD] D[AR] ROT[18.] DEST[Q] NORM $ ;Q=LENGTH,,0 D[MEM] ALU[D+Q] DEST[MEMSTO] JUMP[VIDMLL] NORM $ ;HOLD=BACK,LENGTH+LENGTH,,BEGIN write ;This is the outermost loop. It is gone through twice, once with ;first-half-done off subtracting the previous POG buffer, then with ;first-half-done on adding the display list and copying into the ;POG buffer. ;Form the display list and POG buffer pointers. VIDMHL: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+POG read LENGTH,,BEGINING MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q AR] NORM $ ;AR Q=0,,BEGINING D[IR] DEST[MA] NORM $ ;MA=E read BEGINING MAPF[NORM-RD] DEST[FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;WAIT D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[HOLD] NORM $ ;HOLD=DISP BEGINING,,POG BEGINING D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 57.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+57. write DISP BEGINING,,POG BEGINING ;Initialize the remaining length counter for this piece of glass. MAPF[NORM-RD] D[AR] DEST[Q] NORM $ ;Q=BEGINING POG D[CONST 2] ALU[Q-D] DEST[MA] NORM $ ;MA=BEGINING -2 read max length MAPF[NORM-RD] NORM $ ;WAIT D[MEM] DEST[HOLD] NORM $ ;HOLD=MAX LENGTH Sigh. HOLD and MEM really are different D[AR] ALU[D-1] DEST[MA] STRT-WRT NORM $ ;MA=BEGINING-1 write remaining length ;Check for first half done. MAPF[NORM-RD] COND[HALF] JUMP[VIDMHH] NORM $ ;IF -HALF: ;If first half not done, get length of POG buffer and load the control ;register with the code for subtraction. D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+POG read LENGTH,,BEGINING MAPF[NORM-RD] NORM $ ;WAIT D[MEM] ROT[18.] MASK[15.] DEST[HOLD] NORM $ ;HOLD=LENGTH D[CONST 56.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+56. write LENGTH MAPF[NORM-RD] D[CONST 74] ROT[30.] DEST[IOD] START-OUT NORM $ ;IOD=740000,,000000 MAPF[12] JUMP[VIDMLL] C800 $ ;VLDCTR (subtract) ;If first half done, get length of display list and load control register ;with code for addition. Put length in POG. VIDMHH: D[IR] MASK[18.] DEST[MA] NORM $ ;MA=E read LENGTH MAPF[NORM-RD] D[10 + POG,,POGB] MASK[18.] DEST[Q FIXMAC-MAPF-RD] CYLEN[FIXM] $ ;Q=POGB D[MEM] ROT[18.] MASK[15.] DEST[AR HOLD] NORM $ ;AR,HOLD=LENGTH D[CONST 56.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+56. write LENGTH MAPF[NORM-RD] D[CONST 64] ROT[30.] DEST[IOD] START-OUT NORM $ ;IOD=640000,,000000 MAPF[12] D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[MA] NORM $ ;VLDCTR (add) MA=POGB+POG read BACK,LENGTH,,BEGIN MAPF[NORM-RD] D[AR] ROT[18.] DEST[Q] NORM $ ;Q=LENGTH,,0 D[MEM] ROT[3] MASK[21.] DEST[AR] NORM $ ;AR=BACK,LENGTH,,BEGIN LSH3 ROT21 (LENGTH=0) D[AR] ROT[36. - 3] ALU[DORQ] DEST[MEMSTO] $ ;HOLD=BACK,LENGTH,,BEGIN write ;This is the display list or POG buffer loop. It extracts words and ;determines whether they are characters or vectors. ;If length = 0, go to end of half-done loop. VIDMLL: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 56.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+56. read LENGTH MAPF[NORM-RD] NORM $ ;NORM D[MEM] MASK[18.] COND[OBUS=0] JUMP[VIDMHE] C550 $ ;If LENGTH=0, end ;Check and update remaining length. D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+POG read length,,BEGINING MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] ALU[D-1] DEST[MA] NORM $ ;MA=BEGINING-1 read length remaining MAPF[NORM-RD] NORM $ ;WAIT D[MEM] ALU[D-1] DEST[MEMSTO] COND[OBUS<0] JUMP[VIDMHE] C600 $ ;HOLD=REMAINING LENGTH-1 write remaining length ;If length remaining-1<0, end this half(add or sub) ;Read pointers and chech half. D[CONST 57.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+57. read DISP LIST PTR,,POG BUFF PTR MAPF[NORM-RD] COND[HALF] JUMP[VIDMLH] NORM $ ;If -HALF ;If first half not done, read from POG buffer. D[MEM] MASK[18.] DEST[MA] NORM $ ;MA=POG BUFF PTR read POG WORD MAPF[NORM-RD] JUMP[VIDMLE] NORM $ ;WAIT ;If first half done, read from display list and copy into POG buffer. VIDMLH: D[MEM] ROT[18.] MASK[18.] DEST[MA] NORM $ ;MA=DISP LIST PTR read DISPLAY WORD MAPF[NORM-RD] NORM $ ;WAIT D[MEM] DEST[AR] NORM $ ;AR=DISPLAY WORD D[CONST 57.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+57. read DISP LIST PTR,,POG BUFF PTR MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q] NORM $ ;Q=POG BUFF PTR D[AR] DEST[HOLD] NORM $ ;HOLD=DISPLAY WORD ALU[Q] DEST[MA] STRT-WRT NORM $ ;MA=POG BUFF PTR write DISPLAY WORD MAPF[NORM-RD] D[AR] DEST[HOLD] NORM $ ;HOLD=DISPLAY WORD ;;;Please note the above kludge. This is necessary because HOLD ;;;forgets its data whenever MA changes, even on a write (contrary ;;;to the explanation in the microcode manual). ;Decode opcode of display word (character or vector). VIDMLE: D[MEM] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=NEXT WORD D[MEM] MASK[1] COND[-OBUS=0] JUMP[VIDCHI] C550 $ ;If bit 35=1, character D[MEM] MASK[4] DEST[Q] NORM $ ;Q=4 LSB'S D[CONST 06] ALU[Q#D] COND[OBUS=0] JUMP[VIDVCI] C550 $ ;If 4 lsb's=0110, vector ;Decrement length, and increment pointers. VIDDON: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 56.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+56. read LENGTH MAPF[NORM-RD] NORM $ ;WAIT D[MEM] ALU[D-1] DEST[MEMSTO] NORM $ ;HOLD=LENGTH-1 write LENGTH D[CONST 57.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+57. read DISP LIST PTR,,POG BUFF PTR MAPF[NORM-RD] D[CONST 1,,1] DEST[Q] NORM $ ;Q=1,,1 D[MEM] ALU[D+Q] DEST[MEMSTO] JUMP[VIDMLL] NORM $ ;HOLD=DISP LIST PTR,,POG BUFF PTR + 1,,1 write ;Zero length remaining (so won't try to recover from interrupt). VIDMHE: ALU[0] DEST[HOLD] NORM $ ;HOLD=0 D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 56.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+56. write LENGTH REMAINING ;If first half done, terminate. If not, set HALF flag and loop MAPF[NORM-RD] COND[HALF] JUMP[VIDEND] NORM $ ;If HALF, end D[CONST 1] ROT[35. - 4] DEST[Q] NORM $ ;Q=bit 4 on D[PC] ALU[DORQ] DEST[CRYOV] JUMP[VIDMHL] NORM $ ;Set HALF flag and loop ;Interrupt and End ;Save AMEM and go to MAIN to take interrupt. VIDINT: MAPF[NORM-RD] D[PC] ALU[D-1] DEST[PC] JUMP[VIDSAM] NORM $ ;PC=PC-1 VIDEND: SPEC[CLR-HALF] NORM $ ;Clear HALF VIDSAM: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 1] ROT[6] ALU[Q+D] DEST[Q] NORM $ ;Q=POGB+64. %VIDFOO = 0 .REPEAT 8. [ MAPF[NORM-RD] D[10 + %VIDFOO] DEST[HOLD] NORM $ ;HOLD=AMEM[%VIDFOO] D[CONST %VIDFOO] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+64.+%VIDFOO write %VIDFOO = %VIDFOO + 1 ] MAPF[NORM-RD] ALU[0] DEST[DEV-ADR] JUMP[GOMAIN] NORM $ ;Reset device address, dispatch to interrupt or next instr. ;Recovery ;Restore AMEM. VIDRET: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 1] ROT[6] ALU[Q+D] DEST[Q] NORM $ ;Q=POGB+64. %VIDFOO = 0 .REPEAT 8. [ D[CONST %VIDFOO] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+64.+%VIDFOO read MAPF[NORM-RD] NORM $ ;WAIT D[MEM] DEST[%VIDFOO] DEST-A-MEM NORM $ ;AMEM[%VIDFOO]=MEM %VIDFOO = %VIDFOO + 1 ] ;Check for first half done. D[10 + POG,,POGB] MASK[18.] DEST[Q] COND[HALF] JUMP[VIDRIH] NORM $ ;Q=POGB If -HALF ;If first half not done, default color = modified last color ;and xor mask = -1. D[CONST 48.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR MAPF[NORM-RD] D[CONST 1] ROT[33.] ALU[D-1] DEST[AR] NORM $ ;AR=077777,,777777 D[MEM] DEST[Q] NORM $ ;Q=LAST COLOR,,LAST FONT D[MEM] ROT[2] MASK[2] COND[OBUS=0] JUMP[VIDRIM] C550 $ ;If color>1 D[CONST 7] ROT[33.] ALU[DORQ] DEST[Q] NORM $ ;Q=COLOR 7 (WHITE FROM COLOR) VIDRIM: .REPEAT VIC2 [ D[AR] ALU[DORQ] DEST[IOD] START-OUT NORM $ ;IOD=MODIFIED LAST COLOR 77777,,777777 ];VIC2 .REPEAT 1 - VIC2 [ D[AR] ALU[DORQ] DEST[HOLD] NORM $ ;MEM=MODIFIED LAST COLOR 77777,,777777 D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 59.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+59 write MAPF[NORM-RD] JUMP[VIDRIE] NORM $ ;WAIT ];1-VIC2 ;If first half done, default color = last color, and xor mask = 0. VIDRIH: D[CONST 48.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR MAPF[NORM-RD] D[CONST 1] ROT[33.] ALU[D-1] DEST[AR] NORM $ ;AR=077777,,777777 D[MEM] DEST[Q] NORM $ ;Q=LAST COLOR,,LAST FONT .REPEAT VIC2 [ D[AR] ALU[-D&Q] DEST[IOD] START-OUT NORM $ ;IOD=LAST COLOR 00000,,000000 ];VIC2 .REPEAT 1 - VIC2 [ D[AR] ALU[-D&Q] DEST[HOLD] NORM $ ;MEM=LAST COLOR 00000,,000000 D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 59.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+59 write MAPF[NORM-RD] NORM $ ;WAIT ];1-VIC2 ;Dispatch to saved microcode address to resume from interrupt. VIDRIE: MAPF[10] D[10 + POG,,POGB] MASK[18.] DEST[Q] C800 $ ;VLDCOL Q=POGB D[CONST 58.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+58. read SAVE ADR MAPF[NORM-RD] NORM $ ;WAIT D[MEM] SDISP C500 $ ;Dispatch on SAVE ADR ;Character A-MEM: WORD,,PIXEL3 = 0 YSIZE-1,,FONTPTR = 1 XMAX,,XMIN = 2 YMAX,,YMIN = 3 COLOR = 4 XSIZE3,,XSIZE = 5 LINE,,BYTEPTR = 6 POG,,POGB = 7 ;Note: The zeroth word of the font contains HEIGHT,,WIDTH ;for that font. ;Character body ;Get initial word and 3*pixel. VIDCHI: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] D[CONST 5] ROT[6] ALU[D-1] DEST[Q] NORM $ ;Q=319. D[MEM] MASK[18.] ALU[D+Q] DEST[AR] NORM $ ;AR=X1+319. (0=left hand edge) D[AR] MASK[18.] DEST[Q AR] NORM $ ;Q,AR=X1+319. (eliminate carry across halfwords) D[AR] ROT[1] ALU[D+Q] DEST[AR] PUSHJ[VIDD33] NORM $ ;AR=3*(corrected X coordinate), divide by 33 D[MEM] ROT[18.] ALU[DORQ] DEST[WORD,,PIXEL3] DEST-A-MEM NORM $ ;WORD,,PIXEL3=QUOTIENT,,REMAINDER ;Initialize line and byte pointers. D[MA] ALU[D+1] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] D[CONST 4] ROT[18. + 6] DEST[Q] NORM $ ;Q=256,,0 D[MEM] ROT[18.] SPEC[LEFT] ALU[D+Q] DEST[Q] NORM $ ;Q=Y1+256.,,0 D[CONST 7] ALU[DORQ] DEST[LINE,,BYTEPTR] DEST-A-MEM NORM $ ;LINE,,BYTEPTR=Y1+256.,,7 ;Form XMAX,,XMIN D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[Q] NORM $ ;Q=POGB+POG D[CONST 16.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+16.+POG read XMAX,,XMIN MAPF[NORM-RD] NORM $ ;WAIT D[MEM] DEST[XMAX,,XMIN] DEST-A-MEM NORM $ ;XMAX,,XMIN ;Form YMAX,,YMIN D[MA] DEST[Q] NORM $ ;Q=MA D[CONST 16.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+32.+POG read YMAX,,YMIN MAPF[NORM-RD] NORM $ ;WAIT D[MEM] DEST[YMAX,,YMIN] DEST-A-MEM NORM $ ;YMAX,,YMIN ;Test HALF flag. D[10 + POG,,POGB] MASK[18.] DEST[Q] COND[HALF] JUMP[VIDCHH] NORM $ ;Q=POGB if -HALF ;If not HALF, subtract old image with color=last color. D[CONST 48.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR MAPF[NORM-RD] D[CONST 1] ROT[33.] ALU[D-1] DEST[AR] NORM $ ;AR=077777,,777777 D[MEM] DEST[Q] NORM $ ;Q=LAST COLOR,,LAST FONT D[MEM] ROT[2] MASK[2] COND[OBUS=0] JUMP[VIDCHM] C550 $ ;If color>1 D[CONST 7] ROT[33.] ALU[DORQ] DEST[Q] NORM $ ;Q=COLOR 7 (WHITE FROM COLOR) VIDCHM: D[AR] ALU[DORQ] DEST[COLOR] DEST-A-MEM JUMP[VIDSCL] NORM $ ;COLOR=modified last color 77777,,777777 ;If HALF, add new image with last color. VIDCHH: D[CONST 48.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR MAPF[NORM-RD] D[CONST 1] ROT[33.] ALU[D-1] DEST[AR] NORM $ ;AR=077777,,777777 D[MEM] DEST[Q] NORM $ ;Q=LAST COLOR,,LAST FONT D[AR] ALU[-D&Q] DEST[COLOR] DEST-A-MEM NORM $ ;COLOR=LAST COLOR 00000,,000000 ;This is the character scanning loop. ;Set up font pointer. Flush nulls. VIDSCL: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 57.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+57. read DISPLAY BUFFER POINTER MAPF[NORM-RD] COND[HALF] JUMP[VIDSC1] NORM $ ;If -HALF D[MEM] MASK[18.] DEST[MA] JUMP[VIDSC2] NORM $ ;MA=POG PTR read VIDSC1: D[MEM] ROT[18.] MASK[18.] DEST[MA] NORM $ ;MA=DISP PTR read VIDSC2: MAPF[NORM-RD] D[10 + LINE,,BYTEPTR] DEST[ROTR] NORM $ ;ROTR=LINE,,BYTEPTR D[MEM] ROT[R] MASK[7] DEST[AR] COND[OBUS=0] JUMP[VIDSCN] C550 $ ;AR=ASCII if 0, next character D[CONST 48.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+48. read LAST FONT MAPF[NORM-RD] D[AR] ROT[4] DEST[Q] NORM $ ;Q=0,,ASCII*16. D[MEM] MASK[18.] ALU[D+Q] DEST[YSIZE-1,,FONTPTR] DEST-A-MEM NORM $ ;YSIZE-1,,FONTPTR=0,,LAST FONT+ASCII*16. ;Get width and 3*width of character. D[10 + YSIZE-1,,FONTPTR] MASK[18.] DEST[Q] NORM $ ;Q=FONTPTR D[CONST 15.] ALU[D+Q] DEST[MA] NORM $ ;MA=FONTPTR+15. read YSIZE,,XSIZE MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[AR Q] NORM $ ;AR,Q=0,,XSIZE D[AR] ROT[18.] ALU[D+Q] DEST[Q] NORM $ ;Q=XSIZE,,XSIZE D[AR] ROT[18. + 1] ALU[D+Q] DEST[XSIZE3,,XSIZE] DEST-A-MEM NORM $ ;XSIZE3,,XSIZE=XSIZE*3,,XSIZE ;Initialize YSIZE-1 D[MEM] SPEC[LEFT] DEST[Q] NORM $ ;Q=YSIZE,,0 D[10 + YSIZE-1,,FONTPTR] ALU[DORQ] DEST[Q] NORM $ ;Q=YSIZE,,FONTPTR D[CONST 1] ROT[18.] ALU[Q-D] DEST[YSIZE-1,,FONTPTR] DEST-A-MEM NORM $ ;YSIZE-1,,FONTPTR ;Increment position one character width (right or down). D[MEM] SPEC[LEFT] DEST[Q AR] NORM $ ;AR,Q=YSIZE,,0 D[MEM] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDCCS] C600 $ ;If YSIZE-XSIZE<0, sideways ;Update normal X0,,X1. D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q] NORM $ ;Q=0,,X1 D[10 + XSIZE3,,XSIZE] MASK[18.] ALU[D+Q] DEST[AR] NORM $ ;AR=0,,X1+XSIZE D[MEM] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=X1,,0 D[AR] MASK[18.] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=X1,,X1+XSIZE write X0,,X1 ;Update normal Y0,,Y1. D[MA] ALU[D+1] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q] $ ;Q=0,,Y1 D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[MEMSTO] JUMP[VIDCCL] NORM $ ;HOLD=Y1,,Y1 write Y0,,Y1 ;Update sideways X0,,X1. VIDCCS: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q] $ ;Q=0,,X1 D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=X1,,X1 write X0,,X1 ;Update sidways Y0,,Y1. D[MA] ALU[D+1] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] NORM $ ;WAIT D[MEM] MASK[18.] DEST[Q] NORM $ ;Q=0,,Y1 D[AR] ROT[18.] ALU[Q-D] DEST[AR] NORM $ ;AR=0,,Y1-YSIZE D[MEM] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=Y1,,0 D[AR] MASK[18.] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=Y1,,Y1-YSIZE write Y0,,Y1 ;Check X limits. VIDCCL: D[MA] ALU[D-1] DEST[MA] NORM $ ;MA=POGB+61 read X0,,X1 MAPF[NORM-RD] NORM $ ;WAIT D[MEM] SPEC[LEFT] DEST[Q] NORM $ ;Q=X0,,0 D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDCHE] C600 $ ;if X0,,0-XMIN,,0<0 skip D[10 + XSIZE3,,XSIZE] ROT[18.] SPEC[LEFT] ALU[D+Q] DEST[Q] NORM $ ;Q=X0,,0+XSIZE,,0 D[10 + XMAX,,XMIN] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDCHE] C600 $ ;if XMAX,,0-(X0+XSIZE),,0<0 skip ;Check Y limits. D[MA] ALU[D+1] DEST[MA] NORM $ ;MA=POGB+62 read Y0,,Y1 MAPF[NORM-RD] NORM $ ;WAIT D[MEM] SPEC[LEFT] DEST[Q] NORM $ ;Q=Y0,,0 D[10 + YMAX,,YMIN] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDCHE] C600 $ ;if Y0,,0-YMIN,,0<0 skip D[10 + YSIZE-1,,FONTPTR] SPEC[LEFT] ALU[D+Q] DEST[Q] NORM $ ;Q=Y0,,0+YSIZE-1,,0 D[CONST 1] ROT[18.] ALU[D+Q] DEST[Q] NORM $ ;Q=Y0,,0+YSIZE,,0 D[10 + YMAX,,YMIN] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDCHE] C600 $ ;if YMAX,,0-(Y0+YSIZE),,0<0 skip ;This is the scan line loop for characters. ;Put up first word of this line for this character. VIDCHL: D[10 + YSIZE-1,,FONTPTR] MASK[18.] DEST[Q] NORM $ ;Q=FONTPTR D[10 + YSIZE-1,,FONTPTR] ROT[18.] MASK[18.] ALU[D+Q] DEST[MA] NORM $ ;MA=FONTPTR+YSIZE-1 read DATA MAPF[NORM-RD] D[CONST 33.] DEST[Q] NORM $ ;Q=33. D[10 + WORD,,PIXEL3] MASK[18.] ALU[Q-D] DEST[ROTR] NORM $ ;ROTR=33.-PIXEL3 D[10 + WORD,,PIXEL3] MASK[18.] ALU[Q-D] DEST[MASKR] NORM $ ;MASKR=33.-PIXEL3 D[MEM] ROT[R] MASK[R] DEST[HOLD] PUSHJ[VIDPUT] NORM $ ;HOLD=DATA ROT (33.-PIXEL) MASK (33.-PIXEL) do it ;Determine if there is another word. MAPF[7] D[10 + WORD,,PIXEL3] MASK[18.] DEST[Q] C800 $ ;Q=PIXEL3 VWEVID D[10 + XSIZE3,,XSIZE] ROT[18.] MASK[18.] ALU[D+Q] DEST[Q] NORM $ ;Q=PIXEL3+XSIZE3 D[CONST 33.] ALU[D-Q] COND[-OBUS<0] JUMP[VIDCHS] C600 $ ;If 33.-(PIXEL3+XSIZE3)<0 ;If there is a second word, put it up. D[10 + WORD,,PIXEL3] DEST[Q] NORM $ ;Q=WORD,,PIXEL D[CONST 1] ROT[18.] ALU[Q+D] DEST[WORD,,PIXEL3] DEST-A-MEM NORM $ ;Temporarally increment WORD D[MA] DEST[MA] NORM $ ;Read line of data again. (Not enough state.) D[CONST 30.] DEST[Q] NORM $ ;Q=30. D[10 + WORD,,PIXEL3] MASK[18.] ALU[Q-D] DEST[ROTR] NORM $ ;ROTR=30.-PIXEL3 D[MEM] ROT[R] MASK[33.] DEST[AR] NORM $ ;AR=DATA ROT (30.-PIXEL3) MASK 33. D[CONST 33.] ROT[1] DEST[Q] NORM $ ;Q=66. D[10 + WORD,,PIXEL3] MASK[18.] ALU[Q-D] DEST[Q] NORM $ ;Q=66.-PIXEL3 D[10 + XSIZE3,,XSIZE] ROT[18.] MASK[18.] ALU[Q-D] DEST[MASKR] NORM $ ;MASKR=66.-PIXEL3-XSIZE3 D[AR] DEST[Q] NORM $ ;Q=DATA ROT(30.-PIXEL3) MASK(33.) D[MASK R] ALU[-D&Q] DEST[HOLD] PUSHJ[VIDPUT] NORM $ ;HOLD=DATA ROT(30.-PIXEL3) MASK(66.-PIXEL3-XSIZE3) MAPF[7] D[10 + WORD,,PIXEL3] DEST[Q] NORM $ ;Q=WORD,,PIXEL VWEVID D[CONST 1] ROT[18.] ALU[Q-D] DEST[WORD,,PIXEL3] DEST-A-MEM NORM $ ;Redecrement WORD ;Check for last scan line of character (also interrupts). VIDCHS: MAPF[7] D[10 + YSIZE-1,,FONTPTR] DEST[Q] C800 $ ;Q=YSIZE-1,,FONTPTR VWEVID D[CONST 1] ROT[18.] ALU[Q-D] DEST[YSIZE-1,,FONTPTR] DEST-A-MEM COND[OBUS<0] JUMP[VIDCHE] C600 $ ;If YSIZE-1<0, done COND[-INTRPT] JUMP[VIDCHL] NORM $ ;If no interrupt, loop VIDSAV[VIDCHL] ;Interrupt ;Increment position one character width (right or down). VIDCHE: D[10 + YSIZE-1,,FONTPTR] MASK[18.] DEST[Q] NORM $ ;Q=PONTPTR D[CONST 15.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+15. read YSIZE,,XSIZE MAPF[NORM-RD] NORM $ ;WAIT D[MEM] SPEC[LEFT] DEST[Q] NORM $ ;Q=YSIZE,,0 D[MEM] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDCE2] C600 $ ;If YSIZE-XSIZE<0, sideways D[10 + XSIZE3,,XSIZE] SPEC[LEFT] DEST[Q] NORM $ ;Q=XSIZE3,,0 D[10 + WORD,,PIXEL3] ROT[18.] SPEC[LEFT] ALU[Q+D] DEST[Q] NORM $ ;Q=PIXEL3+XSIZE3,,0 D[CONST 33.] ROT[18.] ALU[Q-D] COND[OBUS<0] JUMP[VIDCE1] C600 $ ;If PIXEL3+XSIZE3-33.<0 skip D[CONST 33.] ROT[18.] ALU[Q-D] DEST[Q] NORM $ ;Q=PIXEL3+XSIZE3-33.,,0 ALU[Q+1] DEST[Q] NORM $ ;Q=PIXEL3+XSIZE3-33.,,1 VIDCE1: ALU[Q] DEST[AR] NORM $ ;AR=NEW PIXEL3,,WORD OFFSET D[10 + WORD,,PIXEL3] SPEC[LEFT] DEST[Q] NORM $ ;Q=WORD,,0 D[AR] ROT[18.] ALU[D+Q] DEST[WORD,,PIXEL3] DEST-A-MEM JUMP[VIDSCN] NORM $ ;WORD,,PIXEL3=WORD+OFFSET,,NEW PIXEL3 VIDCE2: D[10 + LINE,,BYTEPTR] DEST[Q] NORM $ ;Q=LINE,,BYTEPTR D[MEM] SPEC[LEFT] ALU[Q-D] DEST[Q] NORM $ ;Q=LINE-YSIZE,,BYTEPTR ALU[Q] DEST[LINE,,BYTEPTR] DEST-A-MEM NORM $ ;LINE-YSIZE,,BYTEPTR ;Increment byte pointer for next character. VIDSCN: D[10 + LINE,,BYTEPTR] DEST[Q] NORM $ ;Q=LINE,,BYTEPTR D[CONST 7] ALU[Q+D] DEST[AR LINE,,BYTEPTR] DEST-A-MEM NORM $ ;AR,LINE,,BYTEPTR=LINE,,BYTEPTR+7 D[AR] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=BYTEPTR+7,,0 D[CONST 36.] ROT[18.] ALU[D-Q] COND[-OBUS<0] JUMP[VIDSCL] C600 $ ;If 36.,,0-BYTEPTR+7,,0<0 JUMP[VIDDON] NORM $ ;Done ;Divide by 33. (Efficient till 2048./33.) ;AR=DIVIDEND VIDD33: D[AR] ROT[36. - 5] MASK[36. - 5] DEST[Q HOLD] NORM $ ;Q,HOLD=QUOTIENT=AR/32. VID33L: D[MEM] ROT[5] ALU[D+Q] DEST[Q] NORM $ ;Q=33*QUOTIENT D[AR] ALU[D-Q] DEST[Q] COND[-OBUS<0] POPJ C600 $ ;Q=REMAINDER, if < 0 D[MEM] ALU[D-1] DEST[Q HOLD] JUMP[VID33L] NORM $ ;Q,HOLD=QUOTIENT-1 loop ;MEM=QUOTIENT ;Q=REMAINDER ;Put up one word of video ;MEM=DATA VIDPUT: D[10 + LINE,,BYTEPTR] ROT[18.] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE D[10 + YSIZE-1,,FONTPTR] ROT[18.] MASK[18.] ALU[Q-D] DEST[AR] NORM $ ;AR=0,,LINE-(YSIZE-1) D[AR] ROT[5] DEST[Q] NORM $ ;Q=0 LINE 00000 D[CONST 1] ROT[5] ALU[-D&Q] DEST[Q] NORM $ ;Q=0 LINE/2 000000 D[AR] ROT[36. - 1] COND[-OBUS<0] JUMP[VIDPT1] C550 $ ;IF LSB[LINE]=1 D[CONST 1] ROT[14.] ALU[QORD] DEST[Q] NORM $ ;Q=ODD[LINE] LINE/2 000000 VIDPT1: D[10 + WORD,,PIXEL3] ROT[18.] MASK[6] ALU[QORD] DEST[Q] NORM $ ;Q=ODD[LINE] LINE/2 WORD (=interlaced address) D[CONST 7] ROT[6] ALU[Q+D] DEST[Q] NORM $ ;Q=ADR+7*64. D[CONST 6] ALU[Q+D] DEST[IOD] START-OUT NORM $ ;IOD=ADR+7 lines, 6 words MAPF[2] D[MEM] MASK[33.] DEST[Q] C800 $ ;VLDADR Q=DATA D[10 + COLOR] ROT[2] MASK[2] COND[-OBUS=0] PUSHJ[VIDCOL] C800 $ ;If bit(s) 0 or 1 of color on, "color" the word D[10 + COLOR] ALU[D#Q] DEST[IOD] START-OUT C800 $ ;IOD=DATA XOR COLOR MAPF[1] START-IN POPJ C800 $ ;VLDDAT (next line must have MAPF[7] ... C800) ;Make the contents of Q be a colored data word. ;If <2 make it 0, else make it 4. VIDCOL: ALU[Q] DEST[AR] NORM $ ;COPY Q D[AR] ROT[1] ALU[DORQ] DEST[Q] NORM $ ;The 4 bit in each pixel is 1 if either the 4 or 2 bits were 1. D[CONST 33] ALU[-D&Q] DEST[Q] NORM $ ;Zero the 2 and 1 bits. D[CONST 33] ROT[6] ALU[-D&Q] DEST[Q] NORM $ ;Zero the 2 and 1 bits. D[CONST 33] ROT[12.] ALU[-D&Q] DEST[Q] NORM $ ;Zero the 2 and 1 bits. D[CONST 33] ROT[18.] ALU[-D&Q] DEST[Q] NORM $ ;Zero the 2 and 1 bits. D[CONST 33] ROT[24.] ALU[-D&Q] DEST[Q] NORM $ ;Zero the 2 and 1 bits. D[CONST 73] ROT[30.] ALU[-D&Q] DEST[Q] POPJ NORM $ ;Zero the 2 and 1 bits. ;Vector A-MEM: PIXEL,,FRACT = 0 INTEN,,FRACT = 1 XMAX,,XMIN = 2 YMAX,,YMIN = 3 DXDY,,FRACT = 4 A3DYDX,,FRACT = 5 OFFSET,,LINE = 6 POG,,POGB = 7 ;Paint line left .DEFINE VIDLFT[] [ D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE ALU[Q] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,LINE PUSHJ[VIDDT1] NORM $ ;Do it MAPF[7] D[10 + INTEN,,FRACT] DEST[Q] C800 $ ;Q=INTEN,,FRACT VWEVID D[10 + A3DYDX,,FRACT] ALU[Q-D] DEST[Q] NORM $ ;Q=INTEN,,FRACT-A3DYDX,,FRACT ALU[Q] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;AMEM[1]=INTEN,,FRACT-A3DYDX,,FRACT D[CONST 4] ROT[15.] ALU[Q-D-1] COND[OBUS<0] JUMP[. + 9] C600 $ ;If INTEN,,FRACT-0,,377777<0, done. D[10 + OFFSET,,LINE] DEST[Q] NORM $ ;Q=OFFSET,,LINE D[CONST 1] ROT[18.] ALU[Q-D] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET-1,,LINE COND[-INTRPT] JUMP[. - 7] NORM $ ;Loop if no interrupt %VIDFOO = (. - 8) ;NOTE: THIS FORCES EVALUATION BEFORE VIDSAV[%VIDFOO] ; THE MACRO GETS ITS ARGUMENT. ;Interrupt ] ;Paint line right .DEFINE VIDRGT[] [ D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE D[CONST 1] ROT[18.] ALU[QORD] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=1,,LINE PUSHJ[VIDDT1] NORM $ ;Do it (loop to here) MAPF[7] D[10 + INTEN,,FRACT] DEST[Q] C800 $ ;Q=INTEN,,FRACT VWEVID D[10 + A3DYDX,,FRACT] ALU[Q-D] DEST[Q] NORM $ ;Q=INTEN,,FRACT-A3DYDX,,FRACT ALU[Q] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;AMEM[1]=INTEN,,FRACT-A3DYDX,,FRACT D[CONST 4] ROT[15.] ALU[Q-D-1] COND[OBUS<0] JUMP[. + 9] C600 $ ;If INTEN,,FRACT-0,,377777<0, done. D[10 + OFFSET,,LINE] DEST[Q] NORM $ ;Q=OFFSET,,LINE D[CONST 1] ROT[18.] ALU[Q+D] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET+1,,LINE COND[-INTRPT] JUMP[. - 7] NORM $ ;Loop if no interrupt %VIDFOO = (. - 8) ;NOTE: THIS FORCES EVALUATION BEFORE VIDSAV[%VIDFOO] ; THE MACRO GETS ITS ARGUMENT. ;Interrupt ] ;Vector Body ;Extract X field from vector word (extending sign). ;Shift right 1. VIDVCI: D[CONST 1] ROT[8.] ALU[D-1] DEST[AR] NORM $ ;AR=377 D[10 + INTEN,,FRACT] ROT[10.] MASK[10.] DEST[Q] NORM $ ;Q=X D[CONST 1] ROT[9.] ALU[D&Q] COND[OBUS=0] JUMP[VIDVC1] C550 $ ;IF SIGN=1 D[AR] ROT[10.] ALU[DORQ] DEST[Q] NORM $ ;Q=0,,776 X VIDVC1: ALU[Q] DEST[XMAX,,XMIN] DEST-A-MEM NORM $ ;XMAX,,XMIN=0,,X ;Extract Y field from vector word (extending sign). Note the sign change. D[10 + INTEN,,FRACT] ROT[21.] MASK[10.] ALU[0-D] DEST[AR] NORM $ ;Q=-Y D[AR] MASK[10.] DEST[Q] NORM $ ;Q=-Y D[CONST 1] ROT[9.] ALU[D&Q] COND[OBUS=0] JUMP[VIDVC2] C550 $ ;IF SIGN=1 D[CONST 1] ROT[8.] ALU[D-1] DEST[AR] NORM $ ;AR=377 D[AR] ROT[10.] ALU[DORQ] DEST[Q] NORM $ ;Q=0,,776 Y VIDVC2: ALU[Q] DEST[YMAX,,YMIN] DEST-A-MEM NORM $ ;YMAX,,YMIN=0,,Y ;Get default color (0=no change). D[10 + INTEN,,FRACT] ROT[25.] MASK[3] DEST[AR] COND[OBUS=0] JUMP[VIDVC3] C550 $ ;AR=BRT (color) if=0, no change D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 48.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR,,LAST FONT MAPF[NORM-RD] D[AR] ROT[33.] DEST[Q] NORM $ ;Q=COLOR 00000,,000000 D[MEM] MASK[18.] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=COLOR 00000,,LAST FONT write LAST COLOR,,LAST FONT ;Get default font (0=no change). VIDVC3: D[10 + INTEN,,FRACT] ROT[28.] MASK[3] COND[OBUS=0] JUMP[VIDVC4] C550 $ ;if SIZE(FONT)=0, no change D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 48.] ALU[D+Q] DEST[Q MA] NORM $ ;Q,MA=POGB+48 read LAST COLOR,,LAST FONT MAPF[NORM-RD] NORM $ ;WAIT D[MEM] SPEC[LEFT] DEST[AR] NORM $ ;AR=COLOR,,0 D[10 + INTEN,,FRACT] ROT[28.] MASK[3] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+48.+SIZE MAPF[NORM-RD] D[AR] DEST[Q] NORM $ ;Q=COLOR,,0 D[MEM] MASK[18.] ALU[DORQ] DEST[HOLD] NORM $ ;HOLD=COLOR,,FONT D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 48.] ALU[D+Q] DEST[MA] STRT-WRT NORM $ ;Q,MA=POGB+48 write LAST COLOR,,LAST FONT ;Check relative. VIDVC4: MAPF[NORM-RD] D[10 + INTEN,,FRACT] ROT[29.] COND[OBUS<0] JUMP[VIDVC5] C550 $ ;if relative ;If relative, add previous X coordinate. D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] D[10 + XMAX,,XMIN] DEST[Q] NORM $ ;Q=0,,X D[MEM] MASK[18.] ALU[D+Q] DEST[AR] NORM $ ;AR=0,,X+X1 D[MEM] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=X1,,0 D[AR] MASK[18.] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=X1,,X+X1 write X0,,X1 ;If relative, add previous Y coordinate. D[MA] ALU[D+1] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] D[10 + YMAX,,YMIN] DEST[Q] NORM $ ;Q=0,,Y D[MEM] MASK[18.] ALU[D+Q] DEST[AR] NORM $ ;AR=0,,Y+Y1 D[MEM] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=Y1,,0 D[AR] MASK[18.] ALU[DORQ] DEST[MEMSTO] JUMP[VIDVC6] NORM $ ;HOLD=Y1,,Y+Y1 write Y0,,Y1 ;If absolute,just copy X VIDVC5: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] D[10 + XMAX,,XMIN] DEST[Q] NORM $ ;Q=0,,X D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=X1,,X write X0,,X1 ;If absolute, just copy Y D[MA] ALU[D+1] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] D[10 + YMAX,,YMIN] DEST[Q] NORM $ ;Q=0,,Y D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[MEMSTO] NORM $ ;HOLD=Y1,,Y write Y0,,Y1 ;Check type code. If 0, visible vector. (For now, all others invisible.) VIDVC6: D[10 + INTEN,,FRACT] ROT[32.] MASK[2] COND[-OBUS=0] JUMP[VIDDON] C550 $ ;If T NEQ 0, done ;Check first half done. D[10 + POG,,POGB] MASK[18.] DEST[Q] COND[HALF] JUMP[VIDVCH] NORM $ ;Q=POGB If -HALF ;If first half not done, color=modified last color 77777,,777777 D[CONST 48.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR MAPF[NORM-RD] D[CONST 1] ROT[33.] ALU[D-1] DEST[AR] NORM $ ;AR=077777,,777777 D[MEM] DEST[Q] NORM $ ;Q=LAST COLOR,,LAST FONT D[MEM] ROT[2] MASK[2] COND[OBUS=0] JUMP[VIDVIM] C550 $ ;If color>1 D[CONST 7] ROT[33.] ALU[DORQ] DEST[Q] NORM $ ;Q=COLOR 7 (WHITE FROM COLOR) VIDVIM: .REPEAT VIC2 [ D[AR] ALU[DORQ] DEST[IOD] START-OUT NORM $ ;IOD=MODIFIED LAST COLOR 77777,,777777 ];VIC2 .REPEAT 1 - VIC2 [ D[AR] ALU[DORQ] DEST[HOLD] NORM $ ;MEM=MODIFIED LAST COLOR 77777,,777777 D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 59.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+59 write MAPF[NORM-RD] JUMP[VIDVI0] NORM $ ;WAIT ];1-VIC2 ;If first half done, color=default color 00000,,000000 VIDVCH: D[CONST 48.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+48. read LAST COLOR MAPF[NORM-RD] D[CONST 1] ROT[33.] ALU[D-1] DEST[AR] NORM $ ;AR=077777,,777777 D[MEM] DEST[Q] NORM $ ;Q=LAST COLOR,,LAST FONT .REPEAT VIC2 [ D[AR] ALU[-D&Q] DEST[IOD] START-OUT NORM $ ;IOD=LAST COLOR 00000,,000000 ];VIC2 .REPEAT 1 - VIC2 [ D[AR] ALU[-D&Q] DEST[HOLD] NORM $ ;MEM=LAST COLOR 00000,,000000 D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 59.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+59 write MAPF[NORM-RD] NORM $ ;WAIT ];1-VIC2 ;Save X0,,X1 and form XMAX,,XMIN. VIDVI0: MAPF[10] D[10 + POG,,POGB] DEST[Q] C800 $ ;VLDCOL Q=POGB D[CONST 61.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] NORM $ ;WAIT FOR MEM D[MEM] DEST[Q XMAX,,XMIN] DEST-A-MEM NORM $ ;Q,XMAX,,XMIN=X0,,X1 D[MEM] DEST[DXDY,,FRACT] DEST-A-MEM NORM $ ;DXDY,,FRACT=X0,,X1 (for use below) D[MEM] ROT[18.] ALU[Q-D] COND[-OBUS<0] JUMP[VIDVI1] C600 $ ;If X0,,X1-X1,,X0<0 D[MEM] ROT[18.] DEST[XMAX,,XMIN] DEST-A-MEM NORM $ ;XMAX,,XMIN=X1,,X0 ;Save Y0,,Y1 and form YMAX,,YMIN. VIDVI1: D[10 + POG,,POGB] DEST[Q] NORM $ ;Q=POGB D[CONST 62.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] NORM $ ;WAIT FOR MEM D[MEM] DEST[Q YMAX,,YMIN] DEST-A-MEM NORM $ ;Q,YMAX,,YMIN=Y0,,Y1 D[MEM] DEST[A3DYDX,,FRACT] DEST-A-MEM NORM $ ;A3DYDX,,FRACT=Y0,,Y1 (for use below) D[MEM] ROT[18.] ALU[Q-D] COND[-OBUS<0] JUMP[VIDVI2] C600 $ ;If Y0,,Y1-Y1,,Y0<0 D[MEM] ROT[18.] DEST[YMAX,,YMIN] DEST-A-MEM NORM $ ;YMAX,,YMIN=Y1,,Y0 ;Form delta X. Check for vertical vectors. VIDVI2: D[10 + DXDY,,FRACT] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=X1,,0 D[10 + DXDY,,FRACT] SPEC[LEFT] ALU[Q-D] DEST[Q] NORM $ ;Q=DX,,0=X1,,0-X0,,0 ALU[Q] DEST[DXDY,,FRACT] DEST-A-MEM COND[OBUS=0] JUMP[VIDVRV] C550 $ ;DXDY,,FRACT=DX,,0 (for use below) ;If DX=0, vertical vector ;Form delta Y. Check for horizontal vectors. D[10 + A3DYDX,,FRACT] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=Y1,,0 D[10 + A3DYDX,,FRACT] SPEC[LEFT] ALU[Q-D] DEST[Q] NORM $ ;Q=DY,,0=Y1,,0-Y0,,0 ALU[Q] DEST[A3DYDX,,FRACT] DEST-A-MEM COND[OBUS=0] JUMP[VIDHZV] C550 $ ;A3DYDX,,FRACT=DY,,0 (for use below) ;If DY=0, horizontal vector ;Form DXDY and A3DYDX. D[10 + DXDY,,FRACT] DEST[AR] NORM $ ;AR=DIVIDEND=DX,,0 D[10 + A3DYDX,,FRACT] DEST[HOLD] PUSHJ[VIDDIV] NORM $ ;HOLD=DIVISOR=DY,,0 divide ALU[Q] DEST[AR] NORM $ ;AR=DX/DY,,FRACT (abs val) D[10 + DXDY,,FRACT] DEST[Q] NORM $ ;Q=DX D[10 + A3DYDX,,FRACT] ALU[D#Q] COND[-OBUS<0] JUMP[VIDVI3] C550 $ ;IF DX XOR DY < 0 D[AR] ALU[0-D] DEST[AR] NORM $ ;AR=-DX/DY (correct sign) VIDVI3: D[10 + DXDY,,FRACT] DEST[HOLD] NORM $ ;HOLD=DIVISOR=DX D[AR] DEST[DXDY,,FRACT] DEST-A-MEM NORM $ ;DXDY,,FRACT=DX/DY,,FRACT D[10 + A3DYDX,,FRACT] DEST[AR] PUSHJ[VIDDIV] NORM $ ;AR=DIVIDEND=DY divide ALU[Q] DEST[AR] NORM $ ;AR=DY/DX,,FRACT (abs val) D[AR] ROT[1] ALU[Q+D] DEST[A3DYDX,,FRACT] DEST-A-MEM NORM $ ;A3DYDX=3*ABS[DY/DX] ;Initialize OFFSET,,LINE. D[10 + YMAX,,YMIN] MASK[18.] DEST[Q] NORM $ ;Q=0,,YMIN ALU[Q] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,YMIN ;Initialize PIXEL,,FRACT and form boundary limits from POG windows. D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMIN,,0 D[10 + DXDY,,FRACT] COND[-OBUS<0] JUMP[VIDVI4] C550 $ ;If slope negative D[10 + XMAX,,XMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMAX,,0 VIDVI4: ALU[Q] DEST[PIXEL,,FRACT] DEST-A-MEM PUSHJ[VIDVLM] NORM $ ;PIXEL,,FRACT=Q form boundary limits ;Check to see what side of 45 degrees vector's slope is. D[10 + A3DYDX,,FRACT] DEST[Q] NORM $ ;Q=A3DYDX,,FRACT D[CONST 3] ROT[18.] ALU[Q-D] COND[OBUS<0] JUMP[VIDLL2] C600 $ ;If A3DYDX,,FRACT-3,,0<0, other case ;This is the loop for painting 1 line of vectors whose slope is between ;45 degrees (inclusive) and vertical (exclusive). ;Check for above window. VIDLL1: D[10 + YMAX,,YMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMIN,,0 D[10 + OFFSET,,LINE] ROT[18.] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDSL1] C600 $ ;If LINE,,0-YMIN,,0<0, skip line ;Paint left. D[10 + PIXEL,,FRACT] MASK[18.] ALU[D] DEST[Q] NORM $ ;Q=0,,FRACT(PIXEL) D[CONST 1] ROT[18.] ALU[D-Q] DEST[Q AR] NORM $ ;Q,AR=1,,0-0,,FRACT(PIXEL) D[AR] ROT[1] ALU[D+Q] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=3*(1,,0-0,,FRACT(PIXEL)) VIDLFT ;Paint right. D[10 + PIXEL,,FRACT] MASK[18.] DEST[Q AR] NORM $ ;Q=0,,FRACT(PIXEL) D[AR] ROT[1] ALU[D+Q] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=3*0,,FRACT(PIXEL) VIDRGT ;Reset offset and increment line. VIDSL1: D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE ALU[Q+1] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,LINE+1 ;Check for below window. D[10 + OFFSET,,LINE] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=LINE,,0 D[10 + YMAX,,YMIN] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDVEN] C600 $ ;If YMAX,,0-LINE,,0<0, terminate ;Increment X position. D[10 + PIXEL,,FRACT] DEST[Q] NORM $ ;Q=PIXEL,,FRACT D[10 + DXDY,,FRACT] ALU[Q+D] DEST[Q] NORM $ ;Q=PIXEL,,FRACT+DXDY,,FRACT ALU[Q] DEST[PIXEL,,FRACT] DEST-A-MEM JUMP[VIDLL1] NORM $ ;PIXEL,,FRACT=PIXEL,,FRACT+DXDY,,FRACT loop ;This is the loop for vectors whose slope is between 45 degrees (exclusive) ;and horizontal (exclusive). ;Check for above window. VIDLL2: D[10 + YMAX,,YMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMIN,,0 D[10 + OFFSET,,LINE] ROT[18.] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDSL2] C600 $ ;If LINE,,0-YMIN,,0<0, skip line ;Paint left. D[10 + PIXEL,,FRACT] ROT[36. - 2] MASK[16.] DEST[Q] PUSHJ[VIDMUL] NORM $ ;Q=MULTIPLIER(0,,00 16 BIT) multiply D[CONST 3] ROT[18.] ALU[D-Q] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=3,,0-0,,DELTA*A3DYDX,,FRACT VIDLFT ;Paint right. D[10 + PIXEL,,FRACT] ROT[36. - 2] MASK[16.] DEST[Q] NORM $ ;Q=MULTIPLIER(0,,00 16 BIT) D[CONST 1] ROT[16.] ALU[D-Q-1] DEST[Q] PUSHJ[VIDMUL] NORM $ ;Q=1-MULTIPLIER (0,,177777-16 BIT) multiply D[CONST 3] ROT[18.] ALU[D-Q] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=3,,0-0,,DELTA*A3DYDX,,FRACT VIDRGT ;Increment line and reset offset. VIDSL2: D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE ALU[Q+1] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,LINE+1 ;Check for below window. D[10 + OFFSET,,LINE] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=LINE,,0 D[10 + YMAX,,YMIN] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDVEN] C600 $ ;If YMAX,,0-LINE,,0<0, terminate ;Increment X position. D[10 + PIXEL,,FRACT] DEST[Q] NORM $ ;Q=PIXEL,,FRACT D[10 + DXDY,,FRACT] ALU[Q+D] DEST[Q] NORM $ ;Q=PIXEL,,FRACT+DXDY,,FRACT ALU[Q] DEST[PIXEL,,FRACT] DEST-A-MEM JUMP[VIDLL2] NORM $ ;PIXEL,,FRACT=PIXEL,,FRACT+DXDY,,FRACT loop ;Vertical Vectors VIDVRV: PUSHJ[VIDVLM] NORM $ ;Form boundary limits D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+61. read X0,,X1 MAPF[NORM-RD] D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] DEST[Q AR] NORM $ ;Q,AR=XMIN,,0 (AR for use below) D[MEM] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDDON] C600 $ ;If X0,,0-XMIN,,0<0, main loop D[10 + XMAX,,XMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMAX,,0 D[MEM] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDDON] C600 $ ;If XMAX,,0-X0,,0<0, main loop D[AR] DEST[PIXEL,,FRACT] DEST-A-MEM NORM $ ;PIXEL,,FRACT=XMIN,,0 D[10 + YMAX,,YMIN] MASK[18.] DEST[Q] NORM $ ;Q=0,,YMIN ALU[Q] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,YMIN D[CONST 3] ROT[18.] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=3,,0 VIDVRL: D[10 + YMAX,,YMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMAX,,0 D[10 + OFFSET,,LINE] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDVEN] C600 $ ;If YMAX,,0-LINE,,0<0 terminate PUSHJ[VIDDOT] NORM $ ;Do one pixel MAPF[7] D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] C800 $ ;Q=0,,LINE VWEVID ALU[Q+1] DEST[OFFSET,,LINE] DEST-A-MEM COND[-INTRPT] JUMP[VIDVRL] NORM $ ;OFFSET,,LINE=0,,LINE+1 loop if no interrupt VIDSAV[VIDVRL] ;Interrupt ;Horizontal Vectors VIDHZV: PUSHJ[VIDVLM] NORM $ ;Form boundary limits D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 62.] ALU[D+Q] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] D[10 + YMAX,,YMIN] ROT[18.] SPEC[LEFT] DEST[Q AR] NORM $ ;Q,AR=YMIN,,0 (AR for use below) D[MEM] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDDON] C600 $ ;IF Y0,,0-YMIN,,0<0, main loop D[10 + YMAX,,YMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMAX,,0 D[MEM] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDDON] C600 $ ;IF YMAX,,0-Y0,,0<0, main loop D[AR] ROT[18.] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,YMIN D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMIN,,0 ALU[Q] DEST[PIXEL,,FRACT] DEST-A-MEM NORM $ ;PIXEL,,FRACT=XMIN,,0 D[CONST 3] ROT[18.] DEST[INTEN,,FRACT] DEST-A-MEM NORM $ ;INTEN,,FRACT=3,,0 VIDHZL: D[10 + XMAX,,XMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMAX,,0 D[10 + PIXEL,,FRACT] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDVEN] C600 $ ;If XMAX,,0-PIXEL,,0<0, terminate PUSHJ[VIDDOT] NORM $ ;Do one pixel MAPF[7] D[10 + PIXEL,,FRACT] DEST[Q] C800 $ ;Q=PIXEL,,FRACT VWEVID D[CONST 1] ROT[18.] ALU[Q+D] DEST[PIXEL,,FRACT] DEST-A-MEM COND[-INTRPT] JUMP[VIDHZL] NORM $ ;PIXEL,,FRACT=PIXEL+1,,FRACT loop if no interrupt VIDSAV[VIDHZL] ;Interrupt ;Vector endpoint cleanup (subtract away first point if visible) VIDVEN: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 62.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+62. read Y0,,Y1 MAPF[NORM-RD] D[10 + YMAX,,YMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMIN,,0 D[MEM] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDDON] C600 $ ;If Y0,,0-YMIN,,0<0, main loop D[10 + YMAX,,YMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMAX,,0 D[MEM] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDDON] C600 $ ;If YMAX,,0-Y0,,0<0, main loop D[MEM] SPEC[LEFT] DEST[AR] NORM $ ;AR=Y0,,0 (for use below) D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 61.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+62. read X0,,X1 MAPF[NORM-RD] D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMIN,,0 D[MEM] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] JUMP[VIDDON] C600 $ ;If X0,,0-XMIN,,0<0, main loop D[10 + XMAX,,XMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMAX,,0 D[MEM] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] JUMP[VIDDON] C600 $ ;If XMAX,,0-X0,,0<0, main loop D[MEM] SPEC[LEFT] DEST[Q] NORM $ ;Q=X0,,0 ALU[Q] DEST[PIXEL,,FRACT] DEST-A-MEM NORM $ ;PIXEL,,FRACT=X0,,0 D[AR] ROT[18.] MASK[18.] DEST[OFFSET,,LINE] DEST-A-MEM NORM $ ;OFFSET,,LINE=0,,Y0 D[CONST 5] ROT[18.] DEST[INTEN,,FRACT] DEST-A-MEM PUSHJ[VIDDOT] NORM $ ;INTEN,,FRACT=5,,0 Do it MAPF[7] JUMP[VIDDON] C800 $ ;VWEVID main loop ;Output one pixel VIDDOT: D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE ALU[Q] DEST[OFFSET,,LINE] DEST-A-MEM JUMP[VIDDT2] NORM $ ;OFFSET,,LINE=0,,LINE ;Enter here for limit check VIDDT1: D[10 + PIXEL,,FRACT] SPEC[LEFT] DEST[Q] NORM $ ;Q=PIXEL,,0 D[10 + OFFSET,,LINE] SPEC[LEFT] ALU[Q+D] DEST[Q AR] NORM $ ;AR,Q=PIXEL,,0+OFFSET,,0 D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[OBUS<0] POPJ C600 $ ;IF PIXEL,,0-XMIN,,0<0, RETURN D[10 + XMAX,,XMIN] SPEC[LEFT] ALU[D-Q] COND[OBUS<0] POPJ C600 $ ;IF XMAX,,0-PIXEL,,0<0, RETURN .REPEAT VIC2 [ VIDDT2: D[AR] ROT[18.] MASK[18.] DEST[Q] NORM $ ;Q=0,,PIXEL D[10 + OFFSET,,LINE] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[Q] NORM $ ;Q=LINE,,PIXEL D[10 + INTEN,,FRACT] ROT[18.] MASK[3] DEST[AR] NORM $ ;AR=0,,INTEN D[AR] ROT[33.] ALU[QORD] DEST[IOD] START-OUT NORM $ ;IOD=INTEN,LINE,,PIXEL MAPF[13] START-IN C800 $ ;VLDPIX MAPF[2] START-IN C800 $ ;VSYADR MAPF[1] START-IN POPJ C800 $ ;VSYDAT return (Note: Next instructon must have MAPF[7]) ];VIC2 .REPEAT 1 - VIC2 [ VIDDT2: D[10 + OFFSET,,LINE] MASK[18.] DEST[Q] NORM $ ;Q=0,,LINE D[CONST 4] ROT[6] ALU[Q+D] DEST[AR] NORM $ ;AR=0,,LINE+256. D[AR] ROT[5] MASK[14.] DEST[Q] NORM $ ;Q=0 LINE 00000 D[CONST 1] ROT[5] ALU[-D&Q] DEST[Q] NORM $ ;Q=0 LINE/2 000000 D[AR] ROT[36. - 1] COND[-OBUS<0] JUMP[VIDDT3] C550 $ ;IF LSB[LINE]=1 D[CONST 1] ROT[14.] ALU[QORD] DEST[Q] NORM $ ;Q=ODD[LINE] LINE/2 000000 VIDDT3: ALU[Q] DEST[HOLD] NORM $ ;MEM=INTERLACED LINE 000000 D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 60.] ALU[Q+D] DEST[MA] STRT-WRT NORM $ ;MA=POGB+60. write INTERLACED LINE 000000 (temp) MAPF[NORM-RD] D[CONST 5] ROT[6] ALU[D-1] DEST[Q] NORM $ ;Q=319. D[10 + PIXEL,,FRACT] ROT[18.] MASK[18.] ALU[Q+D] DEST[Q] NORM $ ;Q=0,,PIXEL+319. D[10 + OFFSET,,LINE] ROT[18.] MASK[18.] ALU[Q+D] DEST[AR] NORM $ ;Q=0,,PIXEL+0,,OFFSET+319. D[AR] MASK[18.] DEST[Q AR] NORM $ ;Q,AR=0,,PIXEL+OFFSET+319. D[AR] ROT[1] ALU[D+Q] DEST[AR] PUSHJ[VIDD33] NORM $ ;AR=3*corrected PIXEL divide by 33 D[MEM] ROT[18.] SPEC[LEFT] ALU[DORQ] DEST[AR] NORM $ ;AR=QUOTIENT,,REMAINDER=WORD,,PIXEL D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 60.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+60 read INTERLACED LINE 000000 MAPF[NORM-RD] D[AR] ROT[18.] MASK[18.] DEST[Q] NORM $ ;Q=WORD D[MEM] ALU[QORD] DEST[Q] NORM $ ;Q=INTERLACED LINE 000000 + WORD (=interlaced address) D[CONST 7] ROT[6] ALU[Q+D] DEST[Q] NORM $ ;Q=ADR+7*64. D[CONST 6] ALU[Q+D] DEST[IOD] START-OUT NORM $ ;IOD=ADR+7 lines, 6 words MAPF[2] D[AR] MASK[18.] DEST[Q] C800 $ ;VLDADR Q=REMAINDER D[CONST 30.] ALU[D-Q] DEST[ROTR] NORM $ ;ROTR=30-REMAINDER D[10 + INTEN,,FRACT] DEST[Q] NORM $ ;Q=INTEN,,FRACT D[CONST 4] ROT[15.] ALU[Q+D] DEST[AR] NORM $ ;AR=INTEN,,FRACT+0,,400000 D[AR] ROT[18.] MASK[3] DEST[AR] NORM $ ;AR=0,,INTEN D[AR] ROT[R] DEST[AR] NORM $ ;AR=DATA correctly shifted D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[CONST 59.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+59. read COLOR MASK,,MASK MAPF[NORM-RD] D[AR] DEST[Q] NORM $ ;Q=DATA D[MEM] ROT[2] MASK[2] COND[-OBUS=0] PUSHJ[VIDCOL] C550 $ ;If bit(s) 0 or 1 of color on, "color" the word D[MEM] ALU[D#Q] DEST[IOD] START-OUT NORM $ ;IOD=DATA XOR COLOR MAPF[1] START-IN POPJ C800 $ ;VLDDAT (next line must have MAPF[7] ... C800) ];1-VIC2 ;Compute Limits VIDVLM: D[10 + POG,,POGB] MASK[18.] DEST[Q] NORM $ ;Q=POGB D[10 + POG,,POGB] ROT[18.] MASK[4] ALU[Q+D] DEST[Q] NORM $ ;Q=POGB+POG D[CONST 16.] ALU[Q+D] DEST[MA] NORM $ ;MA=POGB+16.+POG read POG XMAX,,XMIN MAPF[NORM-RD] D[10 + XMAX,,XMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMIN,,0 D[MEM] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[-OBUS<0] JUMP[VIDVL1] C600 $ ;If XMIN,,0-POGXMIN,,0<0 D[10 + XMAX,,XMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMAX,,0 D[MEM] MASK[18.] ALU[DORQ] DEST[XMAX,,XMIN] DEST-A-MEM NORM $ ;XMAX,,XMIN=XMAX,,POGXMIN VIDVL1: D[10 + XMAX,,XMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=XMAX,,0 D[MEM] SPEC[LEFT] ALU[D-Q] COND[-OBUS<0] JUMP[VIDVL2] C600 $ ;If POGXMAX,,0-XMAX,,0<0 D[10 + XMAX,,XMIN] MASK[18.] DEST[Q] NORM $ ;Q=0,,XMIN D[MEM] SPEC[LEFT] ALU[DORQ] DEST[Q] NORM $ ;Q=POGXMAX,,XMIN ALU[Q] DEST[XMAX,,XMIN] DEST-A-MEM NORM $ ;XMAX,,XMIN=POGXMAX,,XMIN VIDVL2: D[MA] DEST[Q] NORM $ ;Q=MA D[CONST 16.] ALU[Q+D] DEST[MA] NORM $ ;MA=MA+16. read POG YMAX,,YMIN MAPF[NORM-RD] D[10 + YMAX,,YMIN] ROT[18.] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMIN,,0 D[MEM] ROT[18.] SPEC[LEFT] ALU[Q-D] COND[-OBUS<0] JUMP[VIDVL3] C600 $ ;If YMIN,,0-POGYMIN,,0<0 D[10 + YMAX,,YMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMAX,,0 D[MEM] MASK[18.] ALU[DORQ] DEST[YMAX,,YMIN] DEST-A-MEM NORM $ ;YMAX,,YMIN=YMAX,,POGYMIN VIDVL3: D[10 + YMAX,,YMIN] SPEC[LEFT] DEST[Q] NORM $ ;Q=YMAX,,0 D[MEM] SPEC[LEFT] ALU[D-Q] COND[-OBUS<0] POPJ C600 $ ;If POGYMAX,,0-YMAX,,0<0 D[10 + YMAX,,YMIN] MASK[18.] DEST[Q] NORM $ ;Q=0,,YMIN D[MEM] SPEC[LEFT] ALU[DORQ] DEST[Q] NORM $ ;Q=POGYMAX,,YMIN ALU[Q] DEST[YMAX,,YMIN] DEST-A-MEM POPJ NORM $ ;YMAX,,YMIN=POGYMAX,,YMIN ;Multiply ;A3DYDX,,FRACT=MULTIPLICAND(2 BIT,,16 BIT 00) positive only ;Q=MULTIPLIER(0,,00 16 BIT) positive only VIDMUL: D[10 + A3DYDX,,FRACT] ROT[15.] DEST[AR] NORM $ ;AR=MULTIPLICAND(0 17 BIT,,1 BIT 00000000000000000) ACSEL[AC] ALU[0] DEST[O_AC HOLD] NORM $ ;HOLD=AC for safe keeping AC=0 ;AR=MULTIPLICAND(0 17 BIT,,1 BIT 00000000000000000) ;Q=MULTIPLIER(0,,00 16 BIT) ;MEM=AC storage D[CONST 15.] LLOAD NORM $ ;Loop 16 times D[AR] ACSEL[AC] ALU[MULAC+D] DEST[D4] MASK[3] LOOP[.] NORM $ ;Add AR to AC depending on the low order bit of Q. ;Shift AC,,Q right. High order bit of AC=OVR XOR -IOB<0 ;AC=PRODUCT(0 17 BIT,,18 BIT) D[MEM] ACSEL[AC] DEST[O_AC AR] NORM $ ;AC=AC storage, AR=PRODUCT(0 17 BIT,,18 BIT) D[AR] ROT[36. - 15.] MASK[20.] DEST[Q] POPJ NORM $ ;Q=PRODUCT(2 BIT,,18 BIT) return ;Q=PRODUCT(2 BIT,,18 BIT) ;Divide ;AR=DIVIDEND,,0 ;MEM=DIVISOR,,0 VIDDIV: D[AR] COND[-OBUS<0] JUMP[VIDDV1] C550 $ ;If AR<0 D[AR] ALU[0-D] DEST[AR] NORM $ ;ABS[AR] VIDDV1: D[AR] ROT[18.] ACSEL[AC] DEST[O_AC AR] NORM $ ;AR LSH -18. <-> AC ALU[0] DEST[Q] NORM $ ;Q=0 D[MEM] COND[-OBUS<0] JUMP[VIDDV2] C550 $ ;If MEM<0 D[MEM] ALU[0-D] DEST[HOLD] JUMP[VIDDV2] NORM $ ;ABS[MEM] : (. + 3) - (. \ 4) ;.QUAD-1 VIDDV2: D[CONST 36.] LLOAD NORM $ ;Loop 37 times VIDDVL: D[MEM] ALU[DIVAC-D] ACSEL[AC] DEST[D6] MASK[3] COND[OBUS<0] SLOOP[VIDDVL] C600 $ ;Loop here if remainder positive D[AR] ACSEL[AC] ALU[D] DEST[O_AC AR] POPJ NORM $ ;Swap AR <-> AC and return D[MEM] ALU[DIVAC+D] ACSEL[AC] DEST[D6] MASK[3] COND[OBUS<0] SLOOP[VIDDVL] C600 $ ;Loop here if remainder positive D[AR] ACSEL[AC] DEST[O_AC AR] POPJ NORM $ ;Swap AR <-> AC and return ;Q=QUOTIENT,,FRACT .REPEAT XUCODE [ .USE[OTHER] ;If 8K u-mem present, return to low memory. ]